package com.zsqat.eshop.product.service.impl;

import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsqat.common.utils.PageUtils;
import com.zsqat.common.utils.Query;
import com.zsqat.eshop.product.dao.ProductAttrValueDao;
import com.zsqat.eshop.product.entity.ProductAttrValueEntity;
import com.zsqat.eshop.product.service.ProductAttrValueService;
import org.springframework.transaction.annotation.Transactional;

@Service("productAttrValueService")
public class ProductAttrValueServiceImpl extends ServiceImpl<ProductAttrValueDao, ProductAttrValueEntity> implements ProductAttrValueService {

  @Override
  public PageUtils queryPage(Map<String, Object> params) {
    IPage<ProductAttrValueEntity> page = this.page(
        new Query<ProductAttrValueEntity>().getPage(params),
        new QueryWrapper<>()
    );

    return new PageUtils(page);
  }

  @Override
  public void saveProductAttr(List<ProductAttrValueEntity> collect) {
    this.saveBatch(collect);
  }

  @Override
  public List<ProductAttrValueEntity> baseAttrListforspu(Long spuId) {
    return this.baseMapper.selectList(
        new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
  }

  /**
   * 修改商品规格
   *
   * @param spuId
   * @param entities
   */
  @Transactional(rollbackFor = Exception.class)
  @Override
  public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
    // 1. 删除spuId之前对应的所有属性
    this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));

    // 2. 添加商品规格信息
    List<ProductAttrValueEntity> lstProductAttrValue = entities.stream()
        .map(x -> {
             x.setSpuId(spuId);
             return x;
        }).collect(Collectors.toList());

    // 3. 批量新增
    this.saveBatch(lstProductAttrValue);
  }

  public static void main(String args[]) {
    List<String> list = Stream.of("one", "two", "three", "four")
        .map(String::toUpperCase) // toUpperCase就是一个Function类型
        .collect(Collectors.toList());
    System.out.println(list);
    // 输出结果: [ONE, TWO, THREE, FOUR]
    /*
    public String toUpperCase() {
      return toUpperCase(Locale.getDefault());
    }*/


    List<String> list1 = Stream.of("one", "two", "three", "four")
        .peek(String::toUpperCase)
        .collect(Collectors.toList());
    System.out.println(list1);
    // 输出结果: [one, two, three, four]，和以前一样，什么都没改变呀？？

    // 不知道各位看官看明白Java Stream peek函数和Java Stream map函数的区别了

    class Company {
      private String name;
      private int age;

      public Company(String name, int age) {
        this.name = name;
        this.age = age;
      }

      public String getName() {
        return name;
      }

      public int getAge() {
        return age;
      }

      public void setName(String name) {
        this.name = name;
      }

      public void setAge(int age) {
        this.age = age;
      }

      @Override
      public String toString() {
        return "Company{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
      }
    }

    Company apple = new Company("apple", 44);
    List<Company> list2 = Stream.of(apple)
        //.peek(company -> company.setAge(company.getAge() - 10))
        .map(x -> new Company(x.getName().toUpperCase(), x.getAge() - 10))
        .collect(Collectors.toList());
    System.out.println(list2);
    // 运行结果：[Company{name='APPLE', age=34}]

    Company huawei = new Company("huawei", 44);
    List<Company> list3 = Stream.of(huawei)
        .peek(x -> new Company(x.getName().toUpperCase(), x.getAge() - 10))
        .collect(Collectors.toList());
    System.out.println(list3);
    // 运行结果：[Company{name='huawei', age=44}]，和以前一样，什么都没改变呀？？
    // 为毛呀？
    // peek不能改变stream中元素，如果元素是对象的话，其实改变的仅仅是这个对象的值。
    // new Company(x.getName().toUpperCase(), x.getAge() - 10)
    // 这个新元素和以前Stream以前的元素一毛钱关系都没有，它不会新增到Stream中的。

    Company vivo = new Company("vivo", 44);
    List<Company> list4 = Stream.of(vivo)
        .peek(x -> {
          x.setName(x.getName().toUpperCase());
          x.setAge(x.getAge() - 10);
        })
        .collect(Collectors.toList());
    System.out.println(list4);
    // 执行结果: [Company{name='VIVO', age=34}],又是为毛？可以改变了，和list3有啥区别
    // 它也没有新增到以前Stream，也没有改变Stream以前元素的引用，仅仅更改了引用指向的值。
  }
}
/*
  两个函数的返回值都是一个新的Stream，但是两个函数的参数(peek是Consumer,map是Function)起作用的时机不同。
  map的Function在生成新的Stream之前被执行，新Stream中的元素是上游Stream中元素经Function作用后的值。
  peek函数的Consumer工作在生成Stream之后。

  map函数对Stream中元素执行的是映射操作，会以新的元素(map的结果)填充新的Stream，严格的讲map不是修改原来的元素。
  peek只能消费Stream中的元素，是否可以更改Stream中的元素，取决于Stream中的元素是否是不可变对象。
    如果是不可变对象，则不可修改Stream中的元素；
    如果是可变对象，则可以修改对象的值，但是无法修改对象的引用。


  peek 操作接收的是一个 Consumer<T> 函数。
  顾名思义 peek 操作会按照 Consumer<T> 函数提供的逻辑去消费流中的每一个元素，同时有可能改变元素内部的一些属性。
  Consumer是没有返回值的，它只是对Stream中的元素进行某些操作，但是操作之后的数据并不返回到Stream中，所以Stream中的元素还是原来的元素。

  而map接收一个Function。
  而Function是有返回值的，这意味着对于Stream的元素的所有操作都会作为新的结果返回到Stream中。

  这就是为什么peek String不会发生变化而peek Object会发生变化的原因。
  stream中对象的引用不变，变化的是引用指向的值。
*/
